import pylab;
import networkx as nx;
import scipy.interpolate;
from PyQt4 import QtCore, QtGui;

class LayoutGraph:
    def __init__(self, nodes):
        self.nodes = nodes;
        self.aNodesPos = [];
        self.nNodes = len(nodes);
        
    def applyLayout(self):
        for i in range(len(self.aNodesPos)):
            self.nodes[i].setPos(self.aNodesPos[i]);
    
    def setGraphVizLayout(self, graphVizNodes, sType='dot', pX=-1200, pY=200, nSizeX=3.5, nSizeY=3.5):
        if graphVizNodes is None: return;
        aG = ["dot", "neato", "twopi", "circo"];
        if sType in aG: #GraphViz Layouts
            graphVizNodes.layout(prog = sType);
            for i in range(len(graphVizNodes.nodes())):
                node = graphVizNodes.get_node(i);
                nX, nY = node.attr['pos'].split(",");
                nX = float(nX)*nSizeX + pX;
                nY = float(nY)*-nSizeY + pY;
                self.aNodesPos.append(QtCore.QPointF(nX, nY));
        else: #NetworkX Layouts
            gN = nx.from_agraph(graphVizNodes);
            if sType=="circular":
                aPos = nx.circular_layout(gN);
            elif sType=="random":
                aPos = nx.random_layout(gN);
            elif sType=="shell":
                aPos = nx.shell_layout(gN);
            elif sType=="spring":
                aPos = nx.spring_layout(gN);
            elif sType=="spectral":
                aPos = nx.spectral_layout(gN);
            for i in range(len(aPos)):
                nX, nY = aPos[str(i)];
                nX = float(nX)*nSizeX*500 + pX;
                nY = float(nY)*-nSizeY*500 + pY;
                self.aNodesPos.append(QtCore.QPointF(nX, nY));
    
    def setFlowLayout(self, nRows, nCols, pX, pY, spaceX, spaceY):
        iN = 0;
        self.aNodesPos = [];
        for i in range(nRows):
            iY = pY + i*spaceY;
            for j in range(nCols):
                iX = pX + j*spaceX;
                if iN < self.nNodes:
                    self.aNodesPos.append(QtCore.QPointF(iX, iY));
                    iN += 1;
                
    def setGridLayout(self, tGrid, pX, pY, spaceX, spaceY):
        nCols = len(tGrid[0]);
        nRows = len(tGrid);
        iN = 0;
        self.aNodesPos = [];
        for i in range(nRows):
            iY = pY + i*spaceY;
            for j in range(nCols):
                iX = pX + j*spaceX;
                if iN<self.nNodes and tGrid[i][j]>0:
                    self.aNodesPos.append(QtCore.QPointF(iX, iY));
                    iN += 1;
                    
    def setCircleLayout(self, pX, pY, nSizeX, nSizeY, initVal=0, spaceVal=1.0):
        qPath = QtGui.QPainterPath();
        qPath.addEllipse(QtCore.QPointF(pX, pY), nSizeX, nSizeY);
        nNodes = self.nNodes;
        nPos = initVal;
        self.aNodesPos = [];
        for i in range(nNodes): #@UnusedVariable
            nPos += (1.0/float(nNodes))*spaceVal;
            nPos = nPos-1 if nPos>1 else nPos;
            self.aNodesPos.append(qPath.pointAtPercent(nPos));
                    
    def setCurveLayout(self, points, initVal=0, spaceVal=1.0, p=2):
        #Generate Spline Path
        qPath = QtGui.QPainterPath();
        pathPolygon = QtGui.QPolygonF();
        x, y = [], [];
        for i in range(len(points)):
            x.append(points[i].x());
            y.append(points[i].y());        
        try:
            tck,u = scipy.interpolate.splprep([x,y],k=p); #@UnusedVariable
        except:
            return "Error with the Spline Preparation";
        else:
            unew = pylab.linspace(0,1,50);
            out = scipy.interpolate.splev(unew,tck);
            for i in range(len(out[0])):
                pathPolygon.append(QtCore.QPointF(out[0][i], out[1][i]));
            qPath.moveTo(QtCore.QPointF(points[0].x(), points[0].y()));
            qPath.addPolygon(pathPolygon);
            
            #Add Nodes along the Spline Path
            self.aNodesPos = [];
            nNodes = float(self.nNodes);
            nPos = initVal;
            for i in range(int(nNodes)):
                nPos += (1.0/nNodes)*spaceVal;
                nPos = nPos-1 if nPos>1 else nPos;
                self.aNodesPos.append(qPath.pointAtPercent(nPos));
